package com.boil.qz.safekavass.websocket;

import com.boil.pojo.ResultVo;
import com.boil.qz.safekavass.model.LoginUser;
import com.boil.util.Constants;
import com.boil.util.FastJsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by ChenYong on 2016-10-31.
 * <br>
 * WebSocket 文本服务器，即文本消息处理者。
 */
@Component
public class WebSocketTextServer extends TextWebSocketHandler {
    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(WebSocketTextServer.class);
    /**
     * 所有在线会话，线程安全
     */
    private final List<WebSocketSession> onlineSessions;
    /**
     * 注入 Spring 线程池
     */
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    // 普通初始化块
    {
        onlineSessions = Collections.synchronizedList(new ArrayList<WebSocketSession>());
    }

    /**
     * 默认构造器。
     */
    public WebSocketTextServer() {
        super();
    }

    /**
     * 获取 WebSocket 文本服务器的所有在线会话。
     *
     * @return WebSocket 文本服务器的所哟在线会话
     */
    public List<WebSocketSession> getOnlineSessions() {
        return onlineSessions;
    }

    /**
     * 连接成功时执行。
     *
     * @param session 会话
     * @throws Exception 抛出异常
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        try {
            super.afterConnectionEstablished(session);

            onlineSessions.add(session);

            log.debug("WebSocket 文本服务器的会话：{}，连接成功--->在线会话数：{}", session, onlineSessions.size());
        } catch (Exception e) {
            log.error("WebSocket 文本服务器的会话：{}，连接成功时出现异常，异常信息如下：{}", session, e);
        }
    }

    /**
     * 连接关闭时执行。
     *
     * @param session 会话
     * @param status  状态
     * @throws Exception 抛出异常
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try {
            super.afterConnectionClosed(session, status);

            onlineSessions.remove(session);

            log.debug("WebSocket 文本服务器的会话：{}，连接关闭--->在线会话数：{}", session, onlineSessions.size());
        } catch (Exception e) {
            log.error("WebSocket 文本服务器的会话：{}，连接关闭时出现异常，异常信息如下：{}", session, e);
        }
    }

    /**
     * 连接出错时执行。
     *
     * @param session   会话
     * @param exception 异常
     * @throws Exception 抛出异常
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        try {
            super.handleTransportError(session, exception);

            if (session.isOpen()) {
                session.close();
            }

            onlineSessions.remove(session);

            log.debug("WebSocket 文本服务器的会话：{}，连接出错--->在线会话数：{}", session, onlineSessions.size());
        } catch (Exception e) {
            log.error("WebSocket 文本服务器的会话：{}，连接出错时出现异常，异常信息如下：{}", session, e);
        }
    }

    /**
     * 处理文本消息。
     *
     * @param session 会话
     * @param msg     收到的消息
     * @throws Exception 抛出异常
     */
    @Override
    protected void handleTextMessage(final WebSocketSession session, final TextMessage msg) throws Exception {
        try {
            /*
            Thread htmThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 给 session 加锁，非常重要
                        synchronized (session) {
                            // 获取登录用户
                            LoginUser loginUser = (LoginUser) session.getAttributes().get(Constants.LOGIN_USER);

                            if (loginUser != null) {
                                // 客户端查询当前在线人数
                                if (Constants.ONLINE_SESSION_COUNT == Integer.parseInt(msg.getPayload())) {
                                    // 结果映射
                                    ResultVo resultVo = new ResultVo();
                                    resultVo.setResultCode(Constants.ONLINE_SESSION_COUNT);
                                    resultVo.setResultMsg(Constants.ONLINE_SESSION_COUNT_MSG);
                                    resultVo.setResult(Constants.ONLINE_SESSION_CACHE.size());

                                    session.sendMessage(new TextMessage(FastJsonUtils.bean2Json(resultVo)));

                                    log.debug("WebSocket 文本服务器的会话：{}，会话人：{}--->接收消息：{}", session, loginUser.getLoginid(), msg.getPayload());
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("WebSocket 文本服务器的会话：{}，处理消息时出现异常，异常信息如下：{}", session, e);
                    }
                }
            });

            // 启动线程
            htmThread.start();
            */

            threadPoolTaskExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 获取登录用户
                        LoginUser loginUser = (LoginUser) session.getAttributes().get(Constants.LOGIN_USER);

                        if (loginUser != null) {
                            // 客户端查询当前在线人数
                            if (Constants.ONLINE_SESSION_COUNT == Integer.parseInt(msg.getPayload())) {
                                // 结果映射
                                ResultVo resultVo = new ResultVo();
                                resultVo.setResultCode(Constants.ONLINE_SESSION_COUNT);
                                resultVo.setResultMsg(Constants.ONLINE_SESSION_COUNT_MSG);
                                resultVo.setResult(Constants.ONLINE_SESSION_CACHE.size());

                                session.sendMessage(new TextMessage(FastJsonUtils.bean2Json(resultVo)));

                                log.debug("WebSocket 文本服务器的会话：{}，会话人：{}--->接收消息：{}", session, loginUser.getLoginid(), msg.getPayload());
                            }
                        }
                    } catch (Exception e) {
                        log.error("WebSocket 文本服务器的会话：{}，处理消息时出现异常，异常信息如下：{}", session, e);
                    }
                }
            });
        } catch (Exception e) {
            log.error("WebSocket 文本服务器的会话：{}，处理消息时出现异常，异常信息如下：{}", session, e);
        }
    }

    /**
     * 向客户端发送消息（超级群发）。
     *
     * @param resultVo 结果映射
     */
    public void sendMessage(final ResultVo resultVo) {
        try {
            /*
            Thread smThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (WebSocketSession session : onlineSessions) {
                        try {
                            if (session.isOpen()) {
                                // 给 session 加锁，非常重要
                                synchronized (session) {
                                    // 获取登录用户
                                    LoginUser loginUser = (LoginUser) session.getAttributes().get(Constants.LOGIN_USER);

                                    if ((loginUser != null) && (resultVo != null)) {
                                        // 发送的消息
                                        TextMessage sendMsg = new TextMessage(FastJsonUtils.bean2Json(resultVo));

                                        session.sendMessage(sendMsg);

                                        log.debug("WebSocket 文本服务器的会话：{}，会话人：{}--->发送消息：{}", session, loginUser.getLoginid(), sendMsg.getPayload());
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.error("WebSocket 文本服务器的会话：{}，发送消息时出现异常，异常信息如下：{}", session, e);
                        }
                    }
                }
            });

            // 启动线程
            smThread.start();
            */

            threadPoolTaskExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    for (WebSocketSession session : onlineSessions) {
                        try {
                            if (session.isOpen()) {
                                // 获取登录用户
                                LoginUser loginUser = (LoginUser) session.getAttributes().get(Constants.LOGIN_USER);

                                if ((loginUser != null) && (resultVo != null)) {
                                    // 发送的消息
                                    TextMessage sendMsg = new TextMessage(FastJsonUtils.bean2Json(resultVo));

                                    session.sendMessage(sendMsg);

                                    log.debug("WebSocket 文本服务器的会话：{}，会话人：{}--->发送消息：{}", session, loginUser.getLoginid(), sendMsg.getPayload());
                                }
                            }
                        } catch (Exception e) {
                            log.error("WebSocket 文本服务器的会话：{}，发送消息时出现异常，异常信息如下：{}", session, e);
                        }
                    }
                }
            });
        } catch (Exception e) {
            log.error("WebSocket 文本服务器向客户端发送消息时出现异常，异常信息如下：{}", e);
        }
    }
}